`timescale 1ns/1ps

module adder(input [7:0] a, b,
             output [7:0] y);

  assign y = a + b;
   
endmodule // adder


module piperegPC(clk, in, out, reset);
    input clk,reset;
    input [7:0] in;
    output [7:0] out;

    reg [7:0] out;

  always @ (posedge clk, posedge reset )
    begin
	   if(reset)
		  out = 0;
	   else
		  out = in;
    end
endmodule

module piperegIFID(in1, in2, clk,out1,out2, reset);
    input clk, reset, in2;
    input [11:0] in1;
    output [11:0] out1;
   
	  output reg out2;
	  reg [11:0] out1;

	 
	 always @ (posedge clk)
	 begin
	  if(reset) begin
	     out1 = 0;
	     out2=0;
	    end
	  else begin
	     out1=in1;
	     out2=in2;
	   end	
	 end
endmodule


module piperegIDEX(in1, in2,in3, in4, clk, out1,out2,out3, out4,reset);
  input clk, reset;
  input [11:0] in1, in2;
  input [2:0] in3;
  input in4;
	output [11:0]out1,out2;
	output [2:0] out3;
  output out4;
    
	reg [11:0] out1,out2;
	reg [2:0] out3;
  reg out4;
	 
	 always @ (posedge clk,  posedge reset)
	 begin
	 if(reset) begin
	   out1 = 0;
	   out2 = 0;
	   out3 = 0;
	   out4 = 0;
	 end
	else begin	
	 out1 = in1;
	 out2 = in2;
	 out3 = in3;
	 out4 = in4;
	 end
	end
	 
endmodule


module regfile(clk, we, wd, rd);

              input         clk; 
               input         we; 
               input  [11:0] wd; 
               output [11:0] rd;

  reg [11:0] rf;
  always @(posedge clk)
    if (we) rf <= wd;	
  assign rd = rf;   
endmodule 

module alu(input      [11:0] a, b,
           input      [2:0]  alusrc,   
           output reg [11:0] result);

  wire [11:0] b2, sum, slt;

  assign b2 = (alusrc[1] && alusrc[0]) ? ~b:b; 
  assign sum = a + b2 + alusrc[0];

  always@(*)
    case(alusrc)
      3'b000: result <= a & b2;
      3'b001: result <= a | b2;
      3'b010: result <= sum;
      3'b011: result <= sum;
      3'b100: result <= b2+12'b000000000001;
      

     endcase
endmodule 

module mux2X1_8(in1,in2,out,sel);
    input[7:0]in1,in2;
    output[7:0]out;
    input sel;

    assign out = sel ? in2:in1;

endmodule

module mux2X1_12(in1,in2,out,sel);
    input[11:0]in1,in2;
    output[11:0]out;
    input sel;

    assign out = sel ? in2:in1;
endmodule

